// @Author : zaniu(zzaniu@126.com)
// @Time   : 2021/9/1 17:17
// @Desc   :
//
//                   _ooOoo_
//                  o8888888o
//                  88" . "88
//                  (| -_- |)
//                  O\  =  /O
//               ____/`---'\____
//             .'  \\|     |//  `.
//            /  \\|||  :  |||//  \
//           /  _||||| -:- |||||-  \
//           |   | \\\  -  /// |   |
//           | \_|  ''\---/''  |   |
//           \  .-\__  `-`  ___/-. /
//         ___`. .'  /--.--\  `. . __
//      ."" '<  `.___\_<|>_/___.'  >'"".
//     | | :  `- \`.;`\ _ /`;.`/ - ` : | |
//     \  \ `-.   \_ __\ /__ _/   .-` /  /
// =====`-.____`-.___\_____/___.-`____.-'=====
//                   `=---='
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
//           佛祖保佑       永无BUG
//
package main

import (
	"context"
	"distributedTransaction/proto2go"
	"distributedTransaction/utils"
	"distributedTransaction/utils/nacos"
	"fmt"
	"google.golang.org/grpc"
	"google.golang.org/grpc/codes"
	"google.golang.org/grpc/metadata"
	"google.golang.org/grpc/status"
	"log"
	"net"
	"os"
	"os/signal"
)

type OrderServer struct{}

var sql *utils.Sql

func (inv OrderServer) QueryOrderExists(ctx context.Context, Request *proto2go.QueryOrderExistsRequest) (*proto2go.QueryOrderExistsReply, error) {
	retFlag := false
	ret := sql.Select("orders", "id", map[string]interface{}{"GlobalNo": Request.GlobalNo}, 0)
	n := len(*ret)
	if n > 0 {
		fmt.Println("已查询到订单, 流水号： ", Request.GlobalNo)
		retFlag = true
	} else {
		fmt.Println("未查询到订单, 流水号： ", Request.GlobalNo)
		return &proto2go.QueryOrderExistsReply{Exists: retFlag}, status.Errorf(codes.NotFound, fmt.Sprintf("订单`%s`不存在", Request.GlobalNo))
	}
	return &proto2go.QueryOrderExistsReply{Exists: retFlag}, nil
}

func (inv OrderServer) QueryOrder(ctx context.Context, Request *proto2go.QueryOrderRequest) (*proto2go.QueryOrderReply, error) {
	ret := sql.Select("orders", "*", map[string]interface{}{"UserName": Request.UserName}, 0)
	n := len(*ret)
	if n <= 0 {
		fmt.Println("未查询到订单, 用户： ", Request.UserName)
		return &proto2go.QueryOrderReply{}, status.Errorf(codes.NotFound, fmt.Sprintf("亲爱的`%s`, 您还没有订单哦", Request.UserName))
	}
	fmt.Println("已查询到订单, 用户： ", Request.UserName)
	r := make([]*proto2go.QueryOrderDetailReply, 0)
	tmp := &proto2go.QueryOrderDetailReply{}
	for _, info := range *ret {
		tmp.GlobalNo = info["GlobalNo"].(string)
		tmp.UserName = info["UserName"].(string)
		tmp.GoodsName = info["GoodsName"].(string)
		tmp.GoodsNumber = uint64(info["GoodsNumber"].(int64))
		r = append(r, tmp)
	}
	return &proto2go.QueryOrderReply{Order: r}, nil
}

func (inv OrderServer) CreateOrder(ctx context.Context, Request *proto2go.OrderRequest) (*proto2go.OrderReply, error) {
	// 这里放开的话，订单创建失败, grpc返回Unknown, 会触发消息回查
	fmt.Printf("创建订单失败, 流水号： %s, 用户: %s, 商品： %s, 数量: %d\n", Request.GlobalNo, Request.UserName, Request.GoodsName, Request.GoodsNumber)
	md, ok := metadata.FromIncomingContext(ctx)
	if ok {
		fmt.Println("ok, md = ", md)
	} else {
		fmt.Println("not ok, md = ", md)
	}
	return &proto2go.OrderReply{Flag: false}, status.Errorf(codes.Unknown, "订单创建失败")
	createFlag := false
	ret := sql.Insert("orders", []string{"GlobalNo", "UserName", "GoodsName", "GoodsNumber"}, []interface{}{Request.GlobalNo, Request.UserName, Request.GoodsName, int(Request.GoodsNumber)})
	if ret > 0 {
		createFlag = true
		fmt.Printf("创建订单成功, 流水号： %s, 用户: %s, 商品： %s, 数量: %d\n", Request.GlobalNo, Request.UserName, Request.GoodsName, Request.GoodsNumber)
	} else {
		fmt.Printf("创建订单失败, 流水号： %s, 用户: %s, 商品： %s, 数量: %d\n", Request.GlobalNo, Request.UserName, Request.GoodsName, Request.GoodsNumber)
		return &proto2go.OrderReply{Flag: createFlag}, status.Errorf(codes.Unknown, "订单创建失败")
	}
	return &proto2go.OrderReply{Flag: createFlag}, nil
}

func (inv OrderServer) DeleteOrder(ctx context.Context, Request *proto2go.OrderRequest) (*proto2go.OrderReply, error) {
	deleteFlag := false
	ret := sql.Delete("orders", map[string]interface{}{"GlobalNo": Request.GlobalNo})
	if ret > 0 {
		deleteFlag = true
		fmt.Println("删除订单成功, 流水号： ", Request.GlobalNo)
	} else {
		fmt.Println("删除订单失败, 流水号： ", Request.GlobalNo)
	}
	return &proto2go.OrderReply{Flag: deleteFlag}, nil
}

func (inv OrderServer) QueryOrderDetail(ctx context.Context, Request *proto2go.QueryOrderDetailRequest) (*proto2go.QueryOrderDetailReply, error) {
	ret := sql.Select("orders", "*", map[string]interface{}{"GlobalNo": Request.GlobalNo}, 1)
	n := len(*ret)
	if n <= 0 {
		fmt.Println("未查询到订单, 流水号： ", Request.GlobalNo)
		return &proto2go.QueryOrderDetailReply{}, status.Errorf(codes.NotFound, fmt.Sprintf("订单流水号`%s`不存在", Request.GlobalNo))
	}
	tmp := (*ret)[0]
	fmt.Println("已查询到订单, 流水号： ", Request.GlobalNo)
	info := &proto2go.QueryOrderDetailReply{}
	info.GlobalNo = tmp["GlobalNo"].(string)
	info.UserName = tmp["UserName"].(string)
	info.GoodsName = tmp["GoodsName"].(string)
	info.GoodsNumber = uint64(tmp["GoodsNumber"].(int64))
	return info, nil
}

func register(ip string, port uint64, serverName string) {
	ok, err := nacos.Register(ip, port, serverName)
	if err != nil || !ok {
		fmt.Println("注册失败, err = ", err.Error())
		os.Exit(-1)
	}
	fmt.Println("注册成功")
}

func deregister(ip string, port uint64, serverName string) {
	nacos.Deregister(ip, port, serverName)
}

func main() {
	ip := "127.0.0.1"
	port := 8081
	serverName := "gmb.go.order"
	nacos.ListenServerConfig("dev-data", "dev-group", &utils.GlobalServerConfig)
	sql = utils.NewSql()
	register(ip, uint64(port), serverName)
	orderServer := grpc.NewServer()
	// 将服务注册到 gRPC server 实例
	proto2go.RegisterOrderServer(orderServer, OrderServer{})
	// 监听 8081 端口
	listen, err := net.Listen("tcp", fmt.Sprintf("%s:%d", ip, port))
	defer listen.Close()
	if err != nil {
		panic("net.Listen err: " + err.Error())
	}
	go func() {
		// 运行服务
		if err := orderServer.Serve(listen); err != nil {
			panic("server.Serve err: " + err.Error())
		}
	}()
	quit := make(chan os.Signal)
	signal.Notify(quit, os.Interrupt)
	<-quit
	nacos.CancelListenConfig("dev-data", "dev-group")
	deregister(ip, uint64(port), serverName)
	orderServer.GracefulStop()
	log.Println("服务退出 ...")
}
